﻿using System;
using System.IO;

namespace FirstFloor.Documents.IO
{
    /// <summary>
    /// Encapsulates the request for a single package part request and decrypts the part if encrypted.
    /// </summary>
    public class EncryptedPackagePartRequest
        : IPackagePartRequest
    {
        private IPackagePartRequest request;
        private Uri partUri;
        private IPackageDecrypter decrypter;

        internal EncryptedPackagePartRequest(IPackageReader originalReader, Uri partUri, IPackageDecrypter decrypter)
        {
            this.request = originalReader.CreatePartRequest(partUri);
            this.partUri = partUri;
            this.decrypter = decrypter;
        }

        /// <summary>
        /// Aborts the pending request.
        /// </summary>
        public void Abort()
        {
            this.request.Abort();
        }

        /// <summary>
        /// Begins an asynchronous load of specified part.
        /// </summary>
        /// <param name="callback">The callback.</param>
        /// <param name="state">The state.</param>
        /// <returns>
        /// An <see cref="T:System.IAsyncResult"/> that references the asynchronous request for a response.
        /// </returns>
        public IAsyncResult BeginLoadPart(AsyncCallback callback, object state)
        {
            return this.request.BeginLoadPart(callback, state);
        }

        /// <summary>
        /// Ends an asynchronous load part operation. Return null if the requested part does not exist.
        /// </summary>
        /// <param name="result">The result.</param>
        /// <returns>The part content stream.</returns>
        public Stream EndLoadPart(IAsyncResult result)
        {
            var stream = this.request.EndLoadPart(result);

            if (stream != null) {
                return this.decrypter.DecryptPart(this.partUri, stream);
            }
            return stream;
        }
    }
}
